home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 040 (1987-11-15)(Ossowski, Stefan)(DE)(PD).zip / Taifun 040 (1987-11-15)(Ossowski, Stefan)(DE)(PD).adf / A68k / Operands.c < prev    next >
C/C++ Source or Header  |  1989-01-18  |  15KB  |  524 lines

  1. /*------------------------------------------------------------------*/
  2. /*                                    */
  3. /*              MC68000 Cross Assembler                */
  4. /*                                    */
  5. /*          Copyright    (c) 1985 by Brian R. Anderson            */
  6. /*                                    */
  7. /*         Operand processor - May 31, 1987            */
  8. /*                                    */
  9. /*   This program may be copied    for personal, non-commercial use    */
  10. /*   only, provided that the above copyright notice is included        */
  11. /*   on    all copies of the source code.    Copying    for any    other use   */
  12. /*   without the consent of the    author is prohibited.            */
  13. /*                                    */
  14. /*------------------------------------------------------------------*/
  15. /*                                    */
  16. /*        Originally published (in Modula-2) in            */
  17. /*        Dr.    Dobb's Journal, April, May, and June 1986.          */
  18. /*                                    */
  19. /*    AmigaDOS conversion copyright (c) 1987 by Charlie Gibbs.    */
  20. /*                                    */
  21. /*------------------------------------------------------------------*/
  22.  
  23. #include <stdio.h>
  24. #include "a68kdef.h"
  25. #include "a68kglb.h"
  26.  
  27. /* Functions */
  28. extern int  LineParts(), GetField(), Instructions(), ObjDir();
  29. extern int  GetSize(), ReadSymTab(), OpenIncl();
  30. extern long AddrBndW(),    AddrBndL(), GetValue(),    CalcValue();
  31. extern char *malloc();
  32. extern FILE *fopen();
  33.  
  34. int GetArgs(), GetAReg(), GetInstModeSize(), GetMultReg();
  35.  
  36.  
  37.  
  38. int GetArgs (name) char    *name;
  39. /* Gets    macro arguments    and adds them to FNStack after adding "name".
  40.     Returns the    number of arguments added to the stack.
  41.     Note that this might not be    the full number    of arguments
  42.     provided if    the stack overflowed.                */
  43. {
  44.     register int i, j, narg, instring;
  45.     char currarg[MAXLINE];        /* Current argument */
  46.  
  47.     narg = 0;                /* Argument counter */
  48.  
  49.     Heap2Space (strlen (name) +    1);    /* Find    space for name */
  50.     strcpy (NextFNS, name);        /* Add name to stack */
  51.     NextFNS += strlen (name) + 1;    /* Bump    pointer    */
  52.     if (NextFNS    > High2)
  53.     High2 =    NextFNS;        /* Update high-water mark */
  54.  
  55.     i =    SrcLoc;                /* Now scan Line */
  56.     while ((Line[i] != ' ') && (Line[i] != ';') && (Line[i] != '\0')) {
  57.     j = 0;
  58.     if (instring = (Line[i]    == '<'))    /* String delimiter */
  59.         i++;
  60.     while (1) {
  61.         if (instring) {
  62.         if (Line[i] == '>') {
  63.             i++;
  64.             break;            /* End of string */
  65.         }
  66.         } else {
  67.         if (Line[i] == '\0') break;     /* End of line */
  68.         if (Line[i] == ',') break;      /* End of operand */
  69.         if (Line[i] == ' ') break;      /* End of all operands */
  70.         if (Line[i] == ';') break;      /* Start of comments */
  71.         }
  72.         currarg[j++] = Line[i++];        /* Get a character */
  73.     }
  74.     currarg[j] = '\0';
  75.     Heap2Space (j +    1);            /* Check for space */
  76.     strcpy (NextFNS, currarg);        /* Store argument */
  77.     NextFNS    += strlen (currarg) + 1;    /* Next    available space    */
  78.     if (NextFNS > High2)
  79.         High2 = NextFNS;            /* High-water mark */
  80.     narg++;                    /* Count arguments */
  81.     if (Line[i] == ',')
  82.         i++;            /* Skip    over separator */
  83.     }
  84.     return (narg);            /* Successful completion */
  85. }
  86.  
  87.  
  88.  
  89. EffAdr (EA, Bad) struct    OpConfig *EA; int Bad;
  90. /* Adds    effective address field    to Op (BITSET representing opcode) */
  91. {
  92.     if ((1 << (EA->Mode    - 1)) IN Bad) {
  93.     Error (EA->Loc,    ModeErr);    /* Invalid mode    */
  94.     return;
  95.     } else if (EA->Mode    > 12)        /* Special modes */
  96.     return;
  97.     else if (EA->Mode <    8)        /* Register direct or indirect */
  98.     Op |= ((EA->Mode - 1) << 3) | EA->Rn;
  99.     else
  100.     Op |= 0x0038 | (EA->Mode - 8);    /* Absolute modes */
  101.     OperExt (EA);
  102. }
  103.  
  104.  
  105.  
  106. OperExt    (EA) struct OpConfig *EA;
  107. /* Calculate operand Extension word, and check range of    operands */
  108. {
  109.     switch (EA->Mode) {
  110.     case AbsL:
  111.         break;   /*    No range checking needed */
  112.     case AbsW:
  113.     case ARDisp:
  114.     case PCDisp:
  115.         if ((EA->Value < -32768) ||    (EA->Value > 32767))
  116.         Error (EA->Loc,    SizeErr);
  117.         break;
  118.     case ARDisX:
  119.     case PCDisX:
  120.         if ((EA->Value < -128) || (EA->Value > 127))
  121.         Error (EA->Loc,    SizeErr);
  122.         EA->Value &= 0x00FF;              /* Displacement */
  123.         EA->Value |= EA->Xn    << 12;            /* Index reg. */
  124.         if (EA->X == Areg)       EA->Value |=    0x8000;    /* Addr. Reg. */
  125.         if (EA->Xsize == Long) EA->Value |=    0x0800;    /* Long    reg.  */
  126.         break;
  127.     case Imm:
  128.         if (Size ==    Word) {
  129.         if ((EA->Value < -32768) || (EA->Value > 65535L))
  130.             Error (EA->Loc, SizeErr);
  131.         } else if (Size == Byte)
  132.         if ((EA->Value < -128) || (EA->Value > 255))
  133.             Error (EA->Loc, SizeErr);
  134.         break;
  135.     }
  136. }
  137.  
  138.  
  139.  
  140. GetOperand (oper, op) char oper[]; struct OpConfig *op;
  141. /* Finds mode and value    for source or destination operand. */
  142. {
  143.     register char ch;
  144.     register int  i, j;
  145.     char UCoper[MAXLINE], tempop[MAXLINE];
  146.     int     rloc, MultFlag, opend;
  147.  
  148.     op->Value =    op->Defn = 0;
  149.     op->Mode = Null;
  150.     op->X    = X0;
  151.     op->Hunk = ABSHUNK;
  152.  
  153.     if ((opend = strlen    (oper) - 1) < 0)
  154.     return;                /* Nothing to process */
  155.  
  156.     for    (i = 0;    i <= opend; i++)
  157.     UCoper[i] = toupper (oper[i]);    /* Upper-case version */
  158.     UCoper[i] =    '\0';
  159.  
  160.     if (oper[0]    == '#') {               /* Immediate */
  161.     strcpy (oper, &oper[1]);
  162.     op->Value = GetValue (oper, op->Loc);
  163.     op->Mode  = Imm;
  164.     op->Hunk  = Hunk2;
  165.     op->Defn  = DefLine2;
  166.     return;
  167.     }
  168.  
  169.     i =    IsRegister (oper, opend+1);
  170.     if (i >= 0)    {
  171.     op->Mode = (i &    8) ? ARDir : DReg;    /* Register type */
  172.     op->Rn = i & 7;                /* Register number */
  173.     return;
  174.     } else if (i == -2)    {
  175.     op->Mode = MultiM;            /* Equated register list */
  176.     op->Value = Sym->Val;
  177.     return;
  178.     } else if (strcmp (UCoper, "SP") == 0) {
  179.     op->Mode = ARDir;            /* Stack Pointer */
  180.     op->Rn = 7;                /* (it's A7) */
  181.     return;
  182.     } else if (strcmp (UCoper, "SR") == 0) {
  183.     op->Mode = SR;                /* Status Register */
  184.     return;
  185.     } else if (strcmp (UCoper, "CCR") == 0) {
  186.     op->Mode = CCR;            /* Condition Code Register */
  187.     return;
  188.     } else if (strcmp (UCoper, "USP") == 0) {
  189.     op->Mode = USP;            /* User    Stack Pointer */
  190.     return;
  191.  
  192.     } else if ((oper[0]    == '(') && (oper[opend] == ')')) {
  193.     i = IsRegister (&oper[1], opend-1);
  194.     if (i >= 8 && i    <= 15) {
  195.         op->Mode = ARInd;        /* Address Register indirect */
  196.         op->Rn = i - 8;
  197.         return;
  198.     } else if (i > 0) {
  199.         Error (op->Loc, AddrErr);    /* Data    register is invalid */
  200.         return;
  201.     }    /* else    may be parenthesized expression    */
  202.  
  203.     } else if ((oper[0]    == '(')         /* Post-increment */
  204.     && (oper[opend-1] == ')')
  205.     && (oper[opend] == '+')) {
  206.     op->Mode = ARPost;
  207.     op->Rn = GetAReg (&oper[1], opend-2, op->Loc + 1);
  208.     return;
  209.  
  210.     } else if ((oper[0]    == '-')         /* Pre-decrement */
  211.     && (oper[1]    == '(')
  212.     && (oper[opend] == ')')) {
  213.     i = IsRegister (&oper[2], opend-2);
  214.     if (i >= 8 && i    <= 15) {
  215.         op->Mode = ARPre;
  216.         op->Rn = i - 8;
  217.         return;
  218.     } else if (i > 0) {
  219.         Error (op->Loc, AddrErr);    /* Data    register is invalid */
  220.         return;
  221.     }    /* else    parenthesized expression with leading minus? */
  222.     }
  223.  
  224.     /* Try to split off    displacement (if present).
  225.     We'll assume we have a register expression if the operand
  226.     ends with a parenthesized expression not preceded by an
  227.     operator.  I know this code is a real kludge, but that's
  228.     the result of the bloody syntax.  Thanks, Motorola.    */
  229.  
  230.     j =    strlen(oper) - 1;        /* Last    character */
  231.     if (i = (oper[j] ==    ')'))           /* Trailing parenthesis? */
  232.     while (oper[--j] != '(')        /* Find left parenthesis */
  233.         if (j <= 0)
  234.         break;
  235.     if (j <= 0)                /* Must    not be at beginning */
  236.     i = FALSE;
  237.     if (i) {
  238.     if (j == 1) {
  239.         if (oper[0]    == '-')
  240.         i = FALSE;        /* Leading minus sign */
  241.     } else {
  242.         if (oper[j-1] == '*') {     /* Location counter? */
  243.         if (!IsOperator    (&oper[j-2]) ||    (oper[j-2] == ')'))
  244.             i =    FALSE;        /* No, it's multiplication */
  245.         } else if (IsOperator (&oper[j-1]) && (oper[j-1] !=    ')')) {
  246.         i = FALSE;        /* Preceded by an operator */
  247.         }
  248.     }
  249.     }
  250.  
  251.     if (i) {        /* Looks like a    displacement mode */
  252.     oper[j]    = '\0';
  253.     op->Value = GetValue (oper, op->Loc);    /* Displacement    */
  254.     op->Hunk  = Hunk2;            /* Hunk    number */
  255.     op->Defn  = DefLine2;            /* Line    where defined */
  256.     oper[j++] = '(';                        /* Restore parenthesis */
  257.  
  258.     rloc = op->Loc + j;        /* The register    starts here */
  259.     j = GetField (oper, j, tempop);    /* Get address register    */
  260.     if (oper[j] == '\0')            /* If there's no index register */
  261.         tempop[strlen(tempop)-1] = '\0';    /* chop parenthesis */
  262.  
  263.     if ((tempop[2] == '\0')
  264.     && (toupper (tempop[0])    == 'P')
  265.     && (toupper (tempop[1])    == 'C')) {
  266.         op->Mode = PCDisp;            /* Program Counter */
  267.         if (op->Hunk == CurrHunk) {
  268.         op->Value -= (AddrCnt +    2);    /* Adjust displacement */
  269.         op->Hunk = ABSHUNK;
  270.         }
  271.     } else {
  272.         op->Mode = ARDisp;            /* Address Register */
  273.         op->Rn = GetAReg (tempop, strlen (tempop), rloc);
  274.     }
  275.     if (oper[j] != '\0') {          /* Index register is present */
  276.         if (op->Mode == PCDisp)
  277.         op->Mode = PCDisX;    /* Program Counter indexed */
  278.         else
  279.         op->Mode = ARDisX;    /* Address Register indexed */
  280.         if (oper[j]    != ',')
  281.         Error (op->Loc,    AddrErr);    /* Bad separator */
  282.         j++;                /* Skip    separator */
  283.         rloc = op->Loc + j;            /* Start of index */
  284.         j =    GetField (oper,    j, tempop);    /* Get index register */
  285.         if (oper[j]    == '\0')
  286.         tempop[strlen(tempop)-1]='\0';  /* Chop parenthesis */
  287.         else
  288.         Error (rloc, AddrErr);        /* It better be    there */
  289.  
  290.         op->Xsize =    GetSize    (tempop);    /* Index register size */
  291.         if (op->Xsize == Byte) {
  292.         Error (op->Loc+j-1, SizeErr);    /* Must    not be byte */
  293.         op->Xsize = Word;        /* Make    it word    for now    */
  294.         }
  295.         i =    IsRegister (tempop, strlen (tempop));    /* Get register    */
  296.         op->Xn = i & 7;            /* Index register number */
  297.         if ((i >= 0) && (i <= 7))
  298.         op->X =    Dreg;            /* Data    Register */
  299.         else if ((i    >= 8) && (i <= 15))
  300.         op->X =    Areg;            /* Address Register */
  301.         else
  302.         Error (rloc, AddrErr);        /* Invalid register */
  303.     }
  304.  
  305.     if ((op->Hunk >= 0) && (op->Hunk != ABSHUNK))
  306.         Error (op->Loc, RelErr);    /*  Relocatable    displacement */
  307.     return;
  308.     }
  309.  
  310.     /* Check to    see whether this could be a register list for MOVEM. */
  311.     i =    0;
  312.     MultFlag = FALSE;
  313.     while(1) {
  314.     if ((ch    = UCoper[i++]) == '\0') {
  315.         MultFlag = FALSE;
  316.         break;
  317.     }
  318.     if ((ch    == 'A') || (ch == 'D')) {
  319.         ch = UCoper[i++];
  320.         if (ch == '\0') {
  321.         MultFlag = FALSE;
  322.         break;
  323.         }
  324.         if ((ch >= '0') && (ch <= '7')) {
  325.         ch = UCoper[i++];
  326.         if (ch == '\0')
  327.             break;
  328.         if ((ch    == '/') || (ch == '-'))
  329.             MultFlag = TRUE;
  330.         } else {
  331.         MultFlag = FALSE;
  332.         break;
  333.         }
  334.     } else {
  335.         MultFlag = FALSE;
  336.         break;
  337.     }
  338.     }
  339.     if (MultFlag) {
  340.     op->Mode = MultiM;
  341.     op->Value = 0;        /* We must still get the mask */
  342.     return;
  343.     }
  344.  
  345.     op->Value =    GetValue (oper,    op->Loc);   /* Assume absolute mode */
  346.     op->Hunk  =    Hunk2;
  347.     op->Defn  =    DefLine2;
  348.     if ((Hunk2 == ABSHUNK) && (DefLine2    <= LineCount)
  349.     && (op->Value >= -32768) &&    (op->Value <= 32767))
  350.     op->Mode = AbsW;    /* Fits    in a word */
  351.     else
  352.     op->Mode = AbsL;
  353. }
  354.  
  355.  
  356.  
  357. int GetAReg (op, len, loc) char    op[]; int len, loc;
  358. /* Validate an address register    specification.
  359.     Valid specifications are A0    through    A7 , SP, or an EQUR label.
  360.     The    address    register number    will be    returned if it is valid.
  361.     Otherwise, Error will be called, using "loc" for the error
  362.     location (this is its only use), and zero (A0) will    be returned. */
  363. {
  364.     register int i;
  365.  
  366.     i =    IsRegister (op,    len);        /* Get register    number */
  367.     if ((i >= 8) && (i <= 15))
  368.     return (i - 8);            /* Valid address register */
  369.     else {
  370.     Error (loc, AddrErr);        /* Not an address register */
  371.     return (0);            /* Set to A0 */
  372.     }
  373. }
  374.  
  375.  
  376.  
  377. int IsRegister (op, len) char op[]; int    len;
  378. /* Check whether the current operand is    an address or data register.
  379.     Valid specifications are D0    throuth    D7, A0 through A7, SP,
  380.     or any symbol equated to a register    with the EQUR directive.
  381.     Return values:
  382.     0 through 7 - data registers 0 through 7 respectively
  383.     8 through 15 - address registers 0 through 7 respectively
  384.     -1 - not a recognizable    register
  385.     -2 - Equated register list for MOVEM instruction (REG)    */
  386. {
  387.     char tempop[MAXLINE];
  388.     register char *s;
  389.     register int  i;
  390.  
  391.     if (len == 2) {        /* Two-character specification */
  392.     i = toupper (op[0]);
  393.     if ((i == 'S') && (toupper (op[1]) == 'P')) {
  394.         return (15);            /* Stack Pointer */
  395.     } else if ((op[1] >= '0') && (op[1] <= '7')) {
  396.         if (i == 'A') {
  397.         return (op[1] -    '0' + 8);   /* Address Register */
  398.         } else if (i == 'D') {
  399.         return (op[1] -    '0');       /* Data Register */
  400.         }
  401.     }
  402.     }
  403.     if (!GotEqur)            /* If we have no EQURs to check    */
  404.     return (-1);            /*  don't waste any time here.  */
  405.     for    (i = 0,    s = op;    i < len; i++) {
  406.     if (IsOperator (s))
  407.         return (-1);        /* It sure isn't a label */
  408.     tempop[i] = *s++;
  409.     }
  410.     tempop[i] =    '\0';
  411.     if (ReadSymTab (tempop)) {
  412.     if (Sym->Flags & 0x60) {
  413.         AddRef (LineCount);        /* Found a register or list */
  414.         return ((Sym->Flags    & 0x20)    ? (int)    Sym->Val : -2);
  415.     }
  416.     }
  417.     return (-1);            /* Not a recognizable register */
  418. }
  419.  
  420.  
  421.  
  422. int GetInstModeSize (Mode) int Mode;
  423. /* Determines the size for the various instruction modes. */
  424. {
  425.     switch (Mode) {
  426.     case ARDisp:
  427.     case ARDisX:
  428.     case PCDisp:
  429.     case PCDisX:
  430.     case AbsW:
  431.         return (2);
  432.     case AbsL:
  433.         return (4);
  434.     case MultiM:
  435.         return (0);        /* Accounted for by code generator */
  436.     case Imm:
  437.         if (Size ==    Long)
  438.         return (4);
  439.         else
  440.         return (2);
  441.     default:
  442.         return (0);
  443.     }
  444. }
  445.  
  446.  
  447.  
  448. int GetMultReg (oper, predec, loc) char    oper[];    int predec, loc;
  449. /* Builds a register mask for the MOVEM    instruction */
  450. {
  451.     register char ch;
  452.     register int  i, j;
  453.     int    T1, T2;        /* Temporary variables for registers */
  454.     int    Range;        /* We're processing a range of registers */
  455.     int    RegType;    /* Register type (0=data, 1=address, 2=none) */
  456.     int    MultExt;    /* The result is built here */
  457.  
  458.     MultExt = 0;
  459.     Range = FALSE;
  460.     RegType = 2;
  461.     i =    0;
  462.  
  463.     ch = toupper (oper[i]);
  464.     while (ch != '\0') {
  465.     if (ch == 'A') {
  466.         if (RegType    == 2)
  467.         RegType    = 1;        /* Address register */
  468.         else {
  469.         Error (loc, OperErr);
  470.         return(0);
  471.         }
  472.     } else if (ch == 'D') {
  473.         if (RegType    == 2)
  474.         RegType    = 0;        /* Data    register */
  475.         else {
  476.         Error (loc, OperErr);
  477.         return(0);
  478.         }
  479.     } else if ((ch >= '0') && (ch <= '7')) { /* Register number */
  480.         if (RegType    != 2) {
  481.         T2 = (RegType *    8) + (ch - '0');  /* Bit number */
  482.         if (predec)
  483.             T2 = 15 - T2;    /* Predecrement    reverses mask */
  484.         if (!Range) {
  485.             MultExt |= (1 << T2);    /* Single register */
  486.             T1 = T2;    /* Save    number in case it's a range */
  487.         } else {            /* Range of registers */
  488.             Range = FALSE;
  489.             if (T1 > T2) {
  490.             j = T1;        /* Swap    registers if backwards */
  491.             T1 = T2;
  492.             T2 = j;
  493.             }
  494.             for    (j = T1; j <= T2; j++)
  495.             MultExt    |= (1 << j);    /* Registers in    range */
  496.         }
  497.         } else {
  498.         Error (loc, OperErr);
  499.         return(0);
  500.         }
  501.     } else if (ch == '-') {         /* Range indicator */
  502.         if ((Range == FALSE) && (RegType !=    2) && (i > 0)) {
  503.         RegType    = 2;
  504.         Range =    TRUE;
  505.         } else {
  506.         Error (loc, OperErr);
  507.         return(0);
  508.         }
  509.     } else if (ch == '/') {         /* Separator */
  510.         if ((Range == FALSE) && (RegType !=    2) && (i > 0))
  511.         RegType    = 2;
  512.         else {
  513.         Error (loc, OperErr);
  514.         return(0);
  515.         }
  516.     } else {            /* Garbage */
  517.         Error (loc,    OperErr);
  518.         return(0);
  519.     }
  520.     ch = toupper (oper[++i]);
  521.     }
  522.     return(MultExt);
  523. }
  524.